@tool
class_name BufferProgressBar
extends Control


@onready var value_progress_bar: ProgressBar = $ValueProgressBar
@onready var buffer_effect_bar: ProgressBar = $BufferEffectBar


@export var progress_color: Color:
    set(value):
        progress_color = value
        if Engine.is_editor_hint():
            _set_fill_style_box_flat_bg_color(get_node("ValueProgressBar"), progress_color)
        elif value_progress_bar:
            _set_fill_style_box_flat_bg_color(value_progress_bar, progress_color)

@export var buffer_color: Color:
    set(value):
        buffer_color = value
        if Engine.is_editor_hint():
            _set_fill_style_box_flat_bg_color(get_node("BufferEffectBar"), buffer_color)
        elif buffer_effect_bar:
            _set_fill_style_box_flat_bg_color(buffer_effect_bar, buffer_color)

@export var background_color: Color:
    set(value):
        background_color = value
        if Engine.is_editor_hint():
            _set_background_style_box_flat_bg_color(get_node("BufferEffectBar"), background_color)
        elif buffer_effect_bar:
            _set_background_style_box_flat_bg_color(buffer_effect_bar, background_color)

## 值改变持续时间
@export var value_changed_duration: float:
    set(value):
        value = 0.0 if value < 0 else value
        value_changed_duration = value

## 缓冲动画持续时间，应比值改变持续时间长
@export var buffer_duration: float:
    set(value):
        value = value_changed_duration if value < value_changed_duration else value
        buffer_duration = value

@export var value: float = 0:
    set(val):
        val = clamp(val, min_value, max_value)
        if val == value: return
        var old := value
        value = val
        value_changed.emit(old, value)


@export var min_value: float = 0:
    set(val):
        min_value = val
        get_node("ValueProgressBar").min_value = min_value
        get_node("BufferEffectBar").min_value = min_value


@export var max_value: float = 100:
    set(val):
        max_value = val
        get_node("ValueProgressBar").max_value = max_value
        get_node("BufferEffectBar").max_value = max_value


signal value_changed(ov: float, nv: float)


func _ready() -> void:
    value_changed.connect(
        func(ov: float, nv: float) -> void:
            if nv < ov: _play_reduce_animation(nv)
            else: _play_increase_animation(nv)
    )

    get_node("ValueProgressBar").value = value
    get_node("BufferEffectBar").value = value

    if not Engine.is_editor_hint():
        progress_color = progress_color
        buffer_color = buffer_color
        background_color = background_color


func _set_background_style_box_flat_bg_color(control: Control, color: Color) -> void:
    var style_box := control.get("theme_override_styles/background") as StyleBoxFlat
    style_box.bg_color = color


func _set_fill_style_box_flat_bg_color(control: Control, color: Color) -> void:
    var style_box := control.get("theme_override_styles/fill") as StyleBoxFlat
    style_box.bg_color = color


func _play_reduce_animation(val: float) -> void:
    var value_tween := get_tree().create_tween().bind_node(self)
    var buffer_tween := get_tree().create_tween().bind_node(self)

    var value_bar := get_node("ValueProgressBar") as ProgressBar
    var buffer_bar := get_node("BufferEffectBar") as ProgressBar

    value_tween.tween_property(value_bar, "value", val, value_changed_duration)
    buffer_tween.tween_property(buffer_bar, "value", val, buffer_duration)

    buffer_bar.value = value_bar.value

    value_tween.play()
    buffer_tween.play()


func _play_increase_animation(val: float) -> void:
    var value_tween := get_tree().create_tween().bind_node(self)
    var value_bar := get_node("ValueProgressBar") as ProgressBar
    value_tween.tween_property(value_bar, "value", val, value_changed_duration)
    value_tween.play()
